require(tensorEVD)
set.seed(195021)
# Generate matrices K1 and K2 of dimensions n1 and n2
n1 = 10; n2 = 15
K1 = crossprod(matrix(rnorm(n1*(n1+10)), ncol=n1))
K2 = crossprod(matrix(rnorm(n2*(n2+10)), ncol=n2))
# (a) Example 1. Full design (Kronecker product)
ID1 = rep(seq(n1), each=n2)
ID2 = rep(seq(n2), times=n1)
# Direct EVD of the Hadamard product
K = K1[ID1,ID1]*K2[ID2,ID2]
EVD0 = eigen(K)
# Tensor EVD using K1 and K2
EVD = tensorEVD(K1, K2, ID1, ID2)
# Eigenvectors and eigenvalues are numerically equal
all.equal(EVD0$values, EVD$values)
all.equal(abs(EVD0$vectors), abs(EVD$vectors))
# (b) If a proportion of variance explained is specified,
# only the eigenvectors needed to explain such proportion are derived
alpha = 0.95
EVD = tensorEVD(K1, K2, ID1, ID2, alpha=alpha)
dim(EVD$vectors)
# For the direct EVD
varexp = cumsum(EVD0$values/sum(EVD0$values))
index = 1:which.min(abs(varexp-alpha))
dim(EVD0$vectors[,index])
# (c) Example 2. Incomplete design (Hadamard product)
# Eigenvectors and eigenvalues are no longer equivalent
n = n1*n2 # Sample size n
ID1 = sample(seq(n1), n, replace=TRUE) # Randomly sample of ID1
ID2 = sample(seq(n2), n, replace=TRUE) # Randomly sample of ID2
K = K1[ID1,ID1]*K2[ID2,ID2]
EVD0 = eigen(K)
EVD = tensorEVD(K1, K2, ID1, ID2)
all.equal(EVD0$values, EVD$values)
all.equal(abs(EVD0$vectors), abs(EVD$vectors))
# However, the sum of the eigenvalues is equal to the trace(K)
c(sum(EVD0$values), sum(EVD$values), sum(diag(K)))
# And provide the same approximation for K
K01 = EVD0$vectors%*%diag(EVD0$values)%*%t(EVD0$vectors)
K02 = EVD$vectors%*%diag(EVD$values)%*%t(EVD$vectors)
c(all.equal(K,K01), all.equal(K,K02))
# When n is different from N=n1xn2, both methods provide different
# number or eigenvectors/eigenvalues. The eigen function provides
# a number of eigenvectors equal to the minimum between n and N
# for the tensorEVD, this number is always N
# (d) Sample size n being half of n1 x n2
n = n1*n2/2
ID1 = sample(seq(n1), n, replace=TRUE)
ID2 = sample(seq(n2), n, replace=TRUE)
K = K1[ID1,ID1]*K2[ID2,ID2]
EVD0 = eigen(K)
EVD = tensorEVD(K1, K2, ID1, ID2)
c(eigen=sum(EVD0$values>1E-10), tensorEVD=sum(EVD$values>1E-10))
# (e) Sample size n being twice n1 x n2
n = n1*n2*2
ID1 = sample(seq(n1), n, replace=TRUE)
ID2 = sample(seq(n2), n, replace=TRUE)
K = K1[ID1,ID1]*K2[ID2,ID2]
EVD0 = eigen(K)
EVD = tensorEVD(K1, K2, ID1, ID2)
c(eigen=sum(EVD0$values>1E-10), tensorEVD=sum(EVD$values>1E-10))
Run the code above in your browser using DataLab